package com.vitalfit.security;

import com.vitalfit.model.vo.UserAuthentication;
import com.vitalfit.utils.TokenUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@RequiredArgsConstructor
@Component
@Slf4j
public class JWTRequestFilter extends OncePerRequestFilter {


    private final CustomUserDetailsServiceImpl userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain chain)
            throws ServletException, IOException {

        final String requestURI = request.getRequestURI();
        final String requestMethod = request.getMethod();
        final String authorizationHeader = request.getHeader("Authorization");

        // 如果是登陆注册接口，则直接放行
        if (requestURI.endsWith("/api/v1/auth/customer/login") || requestURI.endsWith("/api/v1/auth/customer/register")
                || requestMethod.equals("OPTIONS") || requestURI.endsWith("/api/v1/auth/admin/login") || requestURI.endsWith("/api/v1/auth/admin/register")) {
            chain.doFilter(request, response);
            return;
        }

        try {
            if (authorizationHeader != null && !authorizationHeader.isEmpty()) {
                Integer userId = TokenUtil.extractUserId(authorizationHeader);
                if (userId == null) {
                    // JWT中未包含有效的userId，返回错误信息给客户端
                    log.warn("JWT does not contain a valid userId");
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token: Missing userId");
                    return;
                }

                UserDetails userDetails = userDetailsService.loadUserByUsername(new UserAuthentication(authorizationHeader,userId).toString());
                if (userDetails == null) {
                    // 用户详情加载失败，返回错误信息给客户端
                    log.warn("Failed to load user details for userId: " + userId);
                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to load user details");
                    return;
                }

                if (TokenUtil.validateToken(authorizationHeader, userDetails.getUsername())) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                } else {
                    // JWT验证失败，返回错误信息给客户端
                    log.warn("JWT token validation failed for userId: " + userId);
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
                    return;
                }
            } else {
                // 没有Authorization头，返回错误信息给客户端
                log.warn("Authorization header is missing");
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization header is missing");
                return;
            }
        } catch (Exception e) {
            // 处理其他异常，如JWT解析异常等
            log.error("An error occurred during JWT authentication", e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "An error occurred during authentication");
        }

        // 如果一切正常，继续执行过滤器链
        chain.doFilter(request, response);
    }

}